package com.module.record.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.module.basic.domain.BasicDevice;
import com.module.basic.mapper.BasicDeviceMapper;
import com.module.common.core.text.Convert;
import com.module.common.utils.DateUtils;
import com.module.common.utils.HexUtils;
import com.module.common.utils.RedisUtils;
import com.module.common.utils.StringUtils;
import com.module.netty.channel.NettyChannel;
import com.module.netty.util.NettyUtil;
import com.module.record.domain.RecordControl;
import com.module.record.mapper.RecordControlMapper;
import com.module.record.service.IRecordControlService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 设备控制记录
 */
@Service
public class RecordControlServiceImpl extends ServiceImpl<RecordControlMapper, RecordControl> implements IRecordControlService {

    @Autowired
    private BasicDeviceMapper basicDeviceMapper;

    @Autowired
    private NettyChannel nettyChannel;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 设备控制记录查询
     * @param RecordControl
     * @return
     */
    @Override
    public List<RecordControl> selectRecordControlList(RecordControl RecordControl) {
        return baseMapper.selectRecordControlList(RecordControl);
    }

    /**
     * 发送设备控制指令
     * @param deviceIds
     * @param controlType
     * @param controlParam
     * @param controlOrder
     * @param operName
     * @return
     */
    @Override
    public String saveRecordControl(String deviceIds, String controlType, String controlParam, String controlOrder, String operName, String remark) {
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for(Long deviceId : Convert.toLongArray(deviceIds)) {
            BasicDevice basicDevice = basicDeviceMapper.selectBasicDeviceByDeviceId(deviceId);
            if (redisUtils.hHasKey("device_online", basicDevice.getDeviceImei())) {
                RecordControl recordControl = new RecordControl();
                recordControl.setDeviceImei(basicDevice.getDeviceImei());
                recordControl.setControlType(controlType);
                recordControl.setControlParam(controlParam);
                recordControl.setControlOrder(controlOrder);
                recordControl.setControlFlag("0");
                recordControl.setCreateBy(operName);
                recordControl.setCreateTime(DateUtils.getNowDate());
                recordControl.setRemark(remark);
                baseMapper.insert(recordControl);

                String channelId = redisUtils.hget("device_online", basicDevice.getDeviceImei());
                if(StringUtils.isNotEmpty(channelId)) {
                    // 发送采集指令码
                    nettyChannel.writeToClient(channelId, HexUtils.hexString2Str(controlOrder).toUpperCase() + "0D0A", remark);

                    successNum++;
                    successMsg.append("<br/>" + successNum + "、采集设备 " + basicDevice.getDeviceImei() + " 发送命令成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、采集设备 " + basicDevice.getDeviceImei() + " 通道断开，发送命令失败");
                }
            } else {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、采集设备 " + basicDevice.getDeviceImei() + " 不在线，发送命令失败");
            }
        }
        if (failureNum > 0)
        {
            failureMsg.insert(0, "很抱歉，抄表失败！共 " + failureNum + " 只采集设备发送命令失败，错误如下：");
            return failureMsg.toString();
        }
        return successMsg.toString();
    }

    /**
     * 保存设备控制记录
     *
     * @param jsonObject
     */
    @Override
    public void insertDeviceInfo(JSONObject jsonObject) {
        JSONObject uploadJson = NettyUtil.parseUpload(jsonObject.getString("returnOrder"));

        LambdaUpdateWrapper<BasicDevice> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.set(BasicDevice::getDeviceImsi, uploadJson.getString("deviceImsi"));
        updateWrapper.set(BasicDevice::getDeviceCsq, uploadJson.getString("deviceCsq"));
        updateWrapper.set(BasicDevice::getDeviceVer, uploadJson.getString("deviceVer"));
        updateWrapper.eq(BasicDevice::getDeviceImei, jsonObject.getString("deviceImei"));
        basicDeviceMapper.update(null, updateWrapper);

        RecordControl recordControl = new RecordControl();
        recordControl.setDeviceImei(jsonObject.getString("deviceImei"));
        recordControl.setControlType("getinfo");
        recordControl.setReturnOrder(jsonObject.getString("returnOrder"));
        recordControl.setControlFlag("1");
        recordControl.setCreateTime(DateUtils.getNowDate());
        baseMapper.insert(recordControl);
    }

    /**
     * 保存设备控制返回结果
     * @param jsonObject
     */
    @Override
    public void updateRecordControl(JSONObject jsonObject) {
        RecordControl recordControl = baseMapper.selectOne(Wrappers.lambdaQuery(RecordControl.class)
                .eq(RecordControl::getDeviceImei, jsonObject.getString("deviceImei"))
                .eq(RecordControl::getControlFlag, "0").apply("DATE(create_time) = DATE(now())")
                .orderByDesc(RecordControl::getCreateTime).last("limit 1"));
        boolean flag = false;
        if(StringUtils.isNotNull(recordControl)) {
            LambdaUpdateWrapper<BasicDevice> updateWrapper = Wrappers.lambdaUpdate();
            if(recordControl.getControlType().equals("setserver")) {
                JSONObject paramJson = JSONObject.parseObject(recordControl.getControlParam());
                String serverIp = paramJson.getString("serverIp");
                String serverPort = paramJson.getString("serverPort");
                String socketType = paramJson.getString("socketType");
                if(socketType.equals("A")) {
                    updateWrapper.set(BasicDevice::getServerA, serverIp + ":" + serverPort);
                } else if(socketType.equals("B")) {
                    updateWrapper.set(BasicDevice::getServerB, serverIp + ":" + serverPort);
                } else if(socketType.equals("C")) {
                    updateWrapper.set(BasicDevice::getServerC, serverIp + ":" + serverPort);
                }
//                updateWrapper.set(BasicDevice::getServerIp, paramJson.getString("serverIp"));
//                updateWrapper.set(BasicDevice::getServerPort, paramJson.getString("serverPort"));

                // 开启通道服务
                String controlOrder = "NAT@AT+SOCKEN1" + paramJson.getString("socketType") + "=ON";
                String channelId = redisUtils.hget("device_online", jsonObject.getString("deviceImei")).toString();
                nettyChannel.writeToClient(channelId, HexUtils.hexString2Str(controlOrder).toUpperCase() + "0D0A", "启动通道" + paramJson.getString("socketType") + "服务");

                flag = true;
            } else if(recordControl.getControlType().equals("getserver")) {
                String returnOrder = jsonObject.getString("returnOrder");
                String msg = HexUtils.hexStr2Str(returnOrder.substring(0, returnOrder.length() - 12));
                String[] msgs = msg.split(",");
                String server = msgs[1] + ":" + msgs[2];
//                updateWrapper.set(BasicDevice::getServerIp, msgs[1]);
//                updateWrapper.set(BasicDevice::getServerPort, msgs[2]);
                if(recordControl.getControlParam().equals("A")) {
                    updateWrapper.set(BasicDevice::getServerA, server);
                } else if(recordControl.getControlParam().equals("B")) {
                    updateWrapper.set(BasicDevice::getServerB, server);
                } else if(recordControl.getControlParam().equals("C")) {
                    updateWrapper.set(BasicDevice::getServerC, server);
                }
            } else if(recordControl.getControlType().equals("offserver")) {
                if(recordControl.getControlParam().equals("A")) {
                    updateWrapper.set(BasicDevice::getServerA, "close");
                } else if(recordControl.getControlParam().equals("B")) {
                    updateWrapper.set(BasicDevice::getServerB, "close");
                } else if(recordControl.getControlParam().equals("C")) {
                    updateWrapper.set(BasicDevice::getServerC, "close");
                }
                flag = true;
            } else if(recordControl.getControlType().equals("getinfo")) {
                String returnOrder = jsonObject.getString("returnOrder");
                String[] contents = HexUtils.hexStr2Str(returnOrder).split("\\r\n+");
                for(String content : contents) {
                    if(content.contains("VERSION:")) {
                        int versionEnd = content.indexOf("(");
                        String deviceVer = content.substring(9, versionEnd);
                        updateWrapper.set(BasicDevice::getDeviceVer, deviceVer);
                    } else if(content.contains("IMEI:")) {
                        String deviceImei = content.substring(6);
                        updateWrapper.set(BasicDevice::getDeviceImei, deviceImei);
                    } else if(content.contains("IMSI:")) {
                        String deviceImsi = content.substring(6);
                        updateWrapper.set(BasicDevice::getDeviceImsi, deviceImsi);
                    } else if(content.contains("ICCID:")) {
                        String deviceIccid = content.substring(7);
                        updateWrapper.set(BasicDevice::getDeviceIccid, deviceIccid);
                    }
                }
            }
            if(updateWrapper.getSqlSet() != null) {
                updateWrapper.eq(BasicDevice::getDeviceImei, recordControl.getDeviceImei());
                basicDeviceMapper.update(null, updateWrapper);
            }
            recordControl.setReturnOrder(jsonObject.getString("returnOrder"));
            recordControl.setControlFlag("1");
            recordControl.setUpdateTime(DateUtils.getNowDate());
            baseMapper.updateById(recordControl);
        }

        if(flag) {
            // 设备重启
            String controlOrder = "NAT@AT+REBOOT";
            String channelId = redisUtils.hget("device_online", jsonObject.getString("deviceImei")).toString();
            nettyChannel.writeToClient(channelId, HexUtils.hexString2Str(controlOrder).toUpperCase() + "0D0A", "设备重启");
        }
    }
}
